package com.cskaoyan.javase.oop1._10block._3static;

/**
 * @description: 静态代码块
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * 什么是静态代码块
 * 定义在类的成员位置，使用以下声明方式声明的代码块，称之为静态代码块
 * static{
 *
 * }
 * 注：静态代码块内部仍属于局部位置，如果嵌套就是一个局部代码块
 *
 * 作用: 随着类加载的过程而执行，静态代码块可以看成是一个在类加载过程中，会自动调用的静态方法
 *      那么它就可以用于在类加载过程中,完成静态成员的赋值
 * 总结一下,静态成员变量的赋值方式(指的是类加载过程中的赋值):
 *      1.默认初始化,具有默认值
 *      2.显式赋值
 *      3.静态代码块赋值
 * 当然除了以上赋值方式,还可以使用构造代码块,构造器赋值,但是它们依赖于创建对象,一定在类加载之后完成
 *
 * 默认初始化,具有默认值是第一步进行的,然后显式赋值和静态代码块赋值是按照代码的书写顺序执行的
 * 谁在代码书写的上面,就先执行,在代码书写的下面,就后执行(后执行的代码是结果)
 * 当然建议把静态代码块写在显式赋值的下面
 *
 * > 静态代码块在实际开发中，并不常见。根据它的一些特点，可以总结一下它的使用场景
 * 1. 复杂的静态成员变量的赋值
 *    - （最经典的）JavaEE中加载JDBC驱动
 * 2. 如果有一段代码从始至终，只运行一次，可以写到静态代码块
 *    - 比如给变量初始化
 *
 * > 一些细节问题
 * 1. 静态代码块可以近似看成一个静态成员方法，所以不能在里面调用非静态（包括this和super）
 * 2. 当需要使用复杂的代码给静态成员变量赋值时，可以使用静态代码块
 *    - 但如果仅仅是简单的赋值，直接显式赋值即可
 * 3. 构造代码块可以给静态成员变量赋值，静态代码块却不能给普通成员代码块赋值
 *    - 类加载在创建对象之前进行，此时没有对象，肯定没有办法赋值
 * 4. 静态代码块和静态成员变量显式赋值的执行顺序，是由类加载的机制保证的
 *    - 类加载的具体流程，我们后面会学习，不必着急
 * 5. 静态代码块也经常被用来测试类加载的顺序
 *    - **一个类的静态代码块如果没有被执行，至少说明它没有被完全类加载**（可能类加载流程走了一半）
 *
 * 类加载的流程: 加载 ---> 连接(链接) ---> 初始化
 * 其中加载和连接是完成对字节码的加载分析,只要完成这两个部分,实际上JVM就足够了解一个类型了
 * 而初始化的过程是为了来执行和static的内容,比如静态成员变量的初始化,静态代码块的执行,静态成员方法的指令加载等都是在初始化的过程中完成
 *
 *
 */
public class Demo {
    public static void main(String[] args) {
        //静态成员out就是依赖于静态代码块完成的赋值
        System.out.println(Phone.price);
    }
}

class Phone {
    String brand;
    static double price = 999;
    //定义在成员位置,使用static修饰大括号,静态代码块
    static {
        price = 8848;
        //System.out.println(brand);
    }

}
